﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using Org.BouncyCastle.Utilities.IO.Pem;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using VIA.Foundation;
using VIA.ImageProcessing;
using VIA.Integration;
using VIA.Integration.LeadShine;
using VIA.Integration.Presentation;
using VIA.Presentation;
using VIA.Presentation.Contracts;
using VIA.SiMoJi.Domain.Electronics;
using VIA.SiMoJi.Domain.Option;

namespace VIA.SiMoJi.Presentation.ViewModel
{
    [ViewModel(typeof(IAxisDebugView))]
    internal class AxisDebugViewModel : EditorViewModel<IAxisDebugView, AxisOption>
    {
        #region Fields
        protected IMessageService _messageService;
        protected IBusyService _busyService;
        protected IDispatcherService _dispatcherService;
        protected IShellService _shellService;
        protected IFileDialogService _dialogService;
        protected ILogger _logger;
        private DmcAxis _axis;
        //private WriteableBitmap _luminanceImageSource;
        //private ImageData3DU imageData3DU;
        private AxisPointParam selecteParam;
        private AutoResetEvent _autoResetEvent = new(true);
        private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
        private double currentPosition;
        private double currentSpeed;
        private bool isMoveEnabel = true;
        //private bool isPositiveLimit;
        //private bool isNegativeLimit;
        //private bool isOriginalSensor;
        private bool isEnableOn;
        private bool isReady;
        private bool isError;
        private bool isAlarm;
        private bool isELP;
        private bool isELN;
        private bool isEMG;
        private bool isORG;
        private bool isSLP;
        private bool isSLN;
        private string axisID;
        private ObservableCollection<AxisPointParam> axisPositions = new();
        private bool isHome;

        #endregion

        #region Commands

        public IRelayCommand BrowseCommand { get; }
        public IRelayCommand SaveAndCloseCommand { get; }
        public IRelayCommand CancelCommand { get; }
        public IRelayCommand MoveCommand { get; }
        public IRelayCommand JogPositiveCommand { get; }
        public IRelayCommand JogNagtiveCommand { get; }
        public IRelayCommand EnableOnCommand { get; }
        public IRelayCommand ClearAlarmCommand { get; }
        public IRelayCommand StopCommand { get; }
        public IRelayCommand HomeCommand { get; }
        public IRelayCommand GetParamCommand { get; }
        public IRelayCommand SetParamCommand { get; }
        public IRelayCommand AllAixsONCommand { get; }
        public IRelayCommand AllAixsOFFCommand { get; }
        public ObservableCollection<AxisPointParam> AxisPositions { get => axisPositions; set => SetProperty(ref axisPositions, value); }
        #endregion

        #region Properties

        public DmcAxis Axis
        {
            get
            {
                return _axis;
            }
            set
            {
                if (SetProperty(ref _axis, value))
                {
                    _axis.Option = Option;
                    //foreach (var item in Option.AxisPositions)
                    //{
                    //    AxisPositions.Add(item);
                    //}
                }

            }
        }
        public string AxisID { get => axisID; set => SetProperty(ref axisID, value); }
        public double CurrentPosition { get => currentPosition; set => SetProperty(ref currentPosition, value); }
        public double CurrentSpeed { get => currentSpeed; set => SetProperty(ref currentSpeed, value); }
        public bool IsMoveEnabel { get => isMoveEnabel; set => SetProperty(ref isMoveEnabel, value); }
        public bool IsEnableOn { get => isEnableOn; set => SetProperty(ref isEnableOn, value); }
        public bool IsReady { get => isReady; set => SetProperty(ref isReady, value); }
        public bool IsError { get => isError; set => SetProperty(ref isError, value); }
        public bool IsHome { get => isHome; set => SetProperty(ref isHome, value); }

        public bool IsAlarm { get => isAlarm; set => SetProperty(ref isAlarm, value); }
        public bool IsELP { get => isELP; set => SetProperty(ref isELP, value); }
        public bool IsELN { get => isELN; set => SetProperty(ref isELN, value); }
        public bool IsEMG { get => isEMG; set => SetProperty(ref isEMG, value); }
        public bool IsORG { get => isORG; set => SetProperty(ref isORG, value); }
        public bool IsSLP { get => isSLP; set => SetProperty(ref isSLP, value); }
        public bool IsSLN { get => isSLN; set => SetProperty(ref isSLN, value); }

        public AxisPointParam SelecteParam { get => selecteParam; set => SetProperty(ref selecteParam, value); }

        #endregion

        public AxisDebugViewModel(IServiceProvider service) : base(service)
        {
            _messageService = service.GetRequiredService<IMessageService>();
            _busyService = service.GetRequiredService<IBusyService>();
            _dispatcherService = service.GetRequiredService<IDispatcherService>();
            _shellService = service.GetRequiredService<IShellService>();
            _dialogService = service.GetRequiredService<IFileDialogService>();
            _dialogService = service.GetRequiredService<IFileDialogService>();
            _logger = service.GetRequiredService<ILogger<AxisDebugViewModel>>();
            SaveAndCloseCommand = _commandFactory.Create(Save);
            CancelCommand = _commandFactory.Create(Cancel);
            MoveCommand = _commandFactory.Create(Move);
            JogPositiveCommand = _commandFactory.Create(JogPositive);
            JogNagtiveCommand = _commandFactory.Create(JogNagtive);
            EnableOnCommand = _commandFactory.Create(EnableOn);
            StopCommand = _commandFactory.Create(Stop);
            HomeCommand = _commandFactory.Create(Home);
            ClearAlarmCommand = _commandFactory.Create(ClearAlarm);
            GetParamCommand = _commandFactory.Create(GetParam);
            SetParamCommand = _commandFactory.Create(SetParam);
            AllAixsONCommand = _commandFactory.Create(GetAllAixsON);
            AllAixsOFFCommand = _commandFactory.Create(AllAixsOFF);
        }

        private void AllAixsOFF()
        {
            Electronic.Default.SetAllAxisOff();
        }

        private void GetAllAixsON()
        {
            Electronic.Default.SetAllAxisOn();
        }

        private void Cancel()
        {
            Option = _currentRecipe.Get<AxisOption>(EditObject.Id);
        }

        private void SetParam()
        {
            //  Axis.SetParam();
        }

        private void GetParam()
        {
            //   Axis.GetParam();
        }

        private void ClearAlarm()
        {
            Axis.ClearAlarm();
        }

        private async void Home()
        {
            await Axis.MoveOriginAsync(default);
            if (!IsError) IsHome = true;
        }

        private void EnableOn()
        {
            if (!Axis.IsServoOn)
                Axis.ServoOn(true);
            else
                Axis.ServoOn(false);
        }

        private void JogNagtive()
        {
            _ = Axis.NegativeAsync();
        }

        private void JogPositive()
        {
            _ = Axis.PostiveAsync();
        }

        public async void Stop()
        {
            await Axis.PauseAsync();
        }

        public async void Move()
        {
            IsMoveEnabel = false;
            await Axis.MoveToAsync(SelecteParam.Position, new VelocityCurve() { Maxvel = SelecteParam.Speed }, default);
            IsMoveEnabel = true;
        }

        public async void Move(AxisPointParam param)
        {
            IsMoveEnabel = false;
            await Axis.MoveToAsync(param.Position, new VelocityCurve() { Maxvel = param.Speed }, default);
            IsMoveEnabel = true;
        }

        public void Refresh()
        {
            Task.Factory.StartNew(async () =>
            {
                await Judger.Sure(() =>
                {
                    try
                    {
                        IsAlarm = Axis.IsAlarm();
                        IsELP = Axis.IsELP();
                        IsELN = Axis.IsELN();
                        IsEMG = Axis.IsEMG();
                        IsORG = Axis.IsORG();
                        IsSLP = Axis.IsSLP();
                        IsSLN = Axis.IsSLN();
                        CurrentPosition = Axis.Current;
                        CurrentSpeed = Axis.CurrentSpeed;
                        IsEnableOn = Axis.IsServoOn;
                        return false;
                    }
                    catch (Exception)
                    {
                        return false;
                    }
                }, _cancellationTokenSource.Token);
            }, _cancellationTokenSource.Token);
        }

        #region Fuction


        void Browse()
        {
            try
            {
                string str = string.Empty;
                bool isFolder = false;
                if (isFolder)
                {
                    OpenFileDialog dialog = new OpenFileDialog();
                    dialog.Title = "选择文件路径";
                    dialog.DefaultExt = "*.*";
                    dialog.Filter = "所有文件|*.*|BMP|*.bmp|TIF|*.tif|PNG|*.png|JPG|*.jpg";
                    if (dialog.ShowDialog(_shellService.ShellWindow) == true)
                    {
                        str = dialog.FileName;
                    }
                }
                else
                {
                    str = _dialogService.ShowFolderBrowserDialog(_shellService.ShellWindow);
                }
                if (!str.IsNullOrEmpty())
                {
                }
            }
            catch (Exception e)
            {
                _messageService.ShowError(View, e);
            }

        }

        private async void View_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _cancellationTokenSource.Cancel();
            await SaveAndClose();
        }

        async Task SaveAndClose()
        {
            await Save();
            Close();
        }

        private void Close()
        {
            try
            {
                View.Close();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
            }
        }

        protected override async Task Save()
        {
            _currentRecipe.Set(Axis.Id, Option);
            await _currentRecipe.SaveAsync().ConfigureAwait(continueOnCapturedContext: false);
            //if (!(base.View is IWindow))
            //{
            //    DialogHost.CloseDialogCommand.Execute();
            //}
        }

        protected override void OnAttach()
        {
            View.Closing += View_Closing;
            base.OnAttach();
        }

        protected override void OnEditObjectChanged(IObject oldObject, IObject newObject)
        {
            if (newObject is DmcAxis axis)
            {
                Axis = axis;
                AxisID = (axis.NoId + 1).ToString();
                _cancellationTokenSource.Cancel();
                _cancellationTokenSource = new();
                Refresh();
            }
        }
        #endregion
    }
}
